package com.crazyhat.crazyhat.service.impl;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.crazyhat.crazyhat.attribute.TokenPayloadEnum;
import com.crazyhat.crazyhat.dto.CommentDTO;
import com.crazyhat.crazyhat.dto.PostAndCommentInfoDTO;
import com.crazyhat.crazyhat.dto.PostDTO;
import com.crazyhat.crazyhat.entity.Comment;
import com.crazyhat.crazyhat.entity.Post;
import com.crazyhat.crazyhat.mapper.CommentMapper;
import com.crazyhat.crazyhat.service.IClubService;
import com.crazyhat.crazyhat.service.ICommentService;
import com.crazyhat.crazyhat.service.IParticipationService;
import com.crazyhat.crazyhat.service.IPostService;
import com.crazyhat.crazyhat.utils.ThreadLocalUtil;
import com.github.yulichang.query.MPJQueryWrapper;

/**
 * <p>
 * 评论 服务实现类
 * </p>
 *
 * @author crazyhat
 * @since 2024-07-05
 */
@Service
public class CommentServiceImpl extends ServiceImpl<CommentMapper, Comment> implements ICommentService {

    @Autowired
    private CommentMapper commentMapper;

    @Autowired
    private IPostService postService;

    @Autowired
    private IParticipationService participationService;

    @Autowired
    private IClubService clubService;

    @Override
    public boolean deleteComment(Integer commentId) {

        Map<String,Object> map=ThreadLocalUtil.get();
        Integer studentId=(Integer)map.get("studentId");

        if (hasDeletePower(studentId, commentId)) {

            commentMapper.deleteById(commentId);
            return true;
        }

        return false;
    }

    /**
     * 查询用户对评论是否有删除权限
     * @param studentId
     * @param commentId
     * @return
     */
    private boolean hasDeletePower(Integer studentId,Integer commentId) {

        Comment comment=commentMapper.selectById(commentId);

        if (comment==null) {
            return false;
        }

        if (comment.getCommentId().equals(studentId)) {

            //评论发布人具有删除评论的权限
            return true;
        }

        Post post=postService.getById(comment.getPostId());

        if (post==null) {
            return false;
        }

        if (post.getStudentId().equals(studentId)) {

            //动态发布人具有删除评论的权限
            return true;
        }

        if (participationService.isCommunityManager(post.getClubId())) {

            //社区管理员具有删除评论的权限
            return true;
        }

        return false;
    }

    /**
     * 获取评论列表，分页
     */
    @Override
    public Page<CommentDTO> getCommentListByPage(Integer postId, Integer pageNum, Integer pageSize) {

        //XXX:由于评论数据表有动态ID的外键约束，如果不验证社团的动态可见范围，则可以省略验证动态是否存在
        Post post=postService.getById(postId);
        if (post==null) {
            return null;
        }

        /*
         * XXX:若需要根据动态对用户是否可见判断是否返回评论列表，则需要涉及三个表的查询，可能会影响查询的性能
         */
        // Map<String,Object> map=ThreadLocalUtil.get();
        // Integer studentId=(Integer)map.get("student_id");
        // Integer clubId=post.getClubId();
        // if (!(clubService.isPostVisibleForUser(clubId, studentId))) {

        //     //若“动态”对用户不可见
        //     return null;
        // }

        Page<CommentDTO> page=new Page<>(pageNum,pageSize);

        MPJQueryWrapper<Comment> mpjQueryWrapper=new MPJQueryWrapper<>();
        mpjQueryWrapper
            .selectAll(Comment.class)
            .select("u.name","u.avatar_url","u.gender")
            .leftJoin("user u on u.student_id = t.commentator_id")
            .eq("t.post_id",postId)
            .orderByDesc("comment_time");

        Page<CommentDTO> commentList=commentMapper.selectJoinPage(page, CommentDTO.class, mpjQueryWrapper);

        return commentList;
    }

    /**
     * 获取动态的全部评论
     */
    @Override
    public List<CommentDTO> getCommentList(Integer postId) {

        //XXX:由于评论数据表有动态ID的外键约束，如果不验证社团的动态可见范围，则可以省略验证动态是否存在
        Post post=postService.getById(postId);
        if (post==null) {
            return null;
        }

        /*
         * XXX:若需要根据动态对用户是否可见判断是否返回评论列表，则需要涉及三个表的查询，可能会影响查询的性能
         */
        // Map<String,Object> map=ThreadLocalUtil.get();
        // Integer studentId=(Integer)map.get("student_id");
        // Integer clubId=post.getClubId();
        // if (!(clubService.isPostVisibleForUser(clubId, studentId))) {

        //     //若“动态”对用户不可见
        //     return null;
        // }

        MPJQueryWrapper<Comment> mpjQueryWrapper=new MPJQueryWrapper<>();
        mpjQueryWrapper
            .selectAll(Comment.class)
            .select("u.name","u.avatar_url","u.gender")
            .leftJoin("user u on u.student_id = t.commentator_id")
            .eq("t.post_id",postId)
            .orderByDesc("comment_time");

        List<CommentDTO> commentList=commentMapper.selectJoinList(CommentDTO.class, mpjQueryWrapper);

        return commentList;
    }

    @Override
    public Comment createComment(Comment comment) {

        if (comment==null) {
            return null;
        }


        Post  post=postService.getById(comment.getPostId());
        if (post==null) {
            //如果所评论的动态不存在
            return null;
        }

        Integer clubId=post.getClubId();

        Map<String,Object> map=ThreadLocalUtil.get();
        Integer studentId=(Integer)map.get(TokenPayloadEnum.StudentId.getValue());


        if (!(clubService.hasCommunityContentPublishPower(clubId, studentId))) {

            //若用户无社区内容发布权限
            throw new RuntimeException("用户无社区内容发布权限");
        }

        //设置评论者ID
        comment.setCommentatorId(studentId);

        comment.setCommentTime(LocalDateTime.now());

        if (commentMapper.insert(comment)>0) {
            return comment;
        } else {
            return null;
        }
    }

    /**
     * 获取动态和评论列表
     */
    @Override
    public PostAndCommentInfoDTO getPostAndCommentInfo(Integer postId) {


        PostDTO post=postService.getPostInfo(postId);

        if (post==null) {
            return null;
        }

        PostAndCommentInfoDTO postAndCommentInfo=new PostAndCommentInfoDTO();
        postAndCommentInfo.setPost(post);
        postAndCommentInfo.setCommentList(getCommentList(postId));

        return postAndCommentInfo;
    }

}
